<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="UTF-8">
	<meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
	<title>nested(嵌套)数据类型 | ElasticSearch 7.7 权威指南中文版</title>
	<meta name="keywords" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <meta name="description" content="ElasticSearch 权威指南中文版, elasticsearch 7, es7, 实时数据分析，实时数据检索" />
    <!-- Give IE8 a fighting chance -->
    <!--[if lt IE 9]>
    <script src="https://oss.maxcdn.com/html5shiv/3.7.2/html5shiv.min.js"></script>
    <script src="https://oss.maxcdn.com/respond/1.4.2/respond.min.js"></script>
    <![endif]-->
	<link rel="stylesheet" type="text/css" href="../static/styles.css" />
	<script>
	var _link = 'nested.html';
    </script>
</head>
<body>
<div class="main-container">
    <section id="content">
        <div class="content-wrapper">
            <section id="guide" lang="zh_cn">
                <div class="container">
                    <div class="row">
                        <div class="col-xs-12 col-sm-8 col-md-8 guide-section">
                            <div style="color:gray; word-break: break-all; font-size:12px;">原英文版地址: <a href="https://www.elastic.co/guide/en/elasticsearch/reference/7.7/nested.html" rel="nofollow" target="_blank">https://www.elastic.co/guide/en/elasticsearch/reference/7.7/nested.html</a>, 原文档版权归 www.elastic.co 所有<br/>本地英文版地址: <a href="../en/nested.html" rel="nofollow" target="_blank">../en/nested.html</a></div>
                        <!-- start body -->
                  <div class="page_header">
<strong>重要</strong>: 此版本不会发布额外的bug修复或文档更新。最新信息请参考 <a href="https://www.elastic.co/guide/en/elasticsearch/reference/current/index.html" rel="nofollow">当前版本文档</a>。
</div>
<div id="content">
<div class="breadcrumbs">
<span class="breadcrumb-link"><a href="index.html">Elasticsearch 权威指南 [7.7]</a></span>
»
<span class="breadcrumb-link"><a href="mapping.html">映射</a></span>
»
<span class="breadcrumb-link"><a href="mapping-types.html">字段数据类型</a></span>
»
<span class="breadcrumb-node">nested(嵌套)数据类型</span>
</div>
<div class="navheader">
<span class="prev">
<a href="keyword.html">« keyword(关键词)数据类型</a>
</span>
<span class="next">
<a href="number.html">numeric(数值)数据类型 »</a>
</span>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h2 class="title">
<a id="nested"></a>nested(嵌套)数据类型
</h2>
</div></div></div>

<p><code class="literal">nested</code>类型是<a class="xref" href="object.html" title="object数据类型" rel="nofollow"><code class="literal">object</code></a>数据类型的一个特殊版本，它允许以一种可以相互独立查询的方式对对象数组进行索引。</p>
<div class="tip admon">
<div class="icon"></div>
<div class="admon_content">
<p>
当摄入包含大量任意键的键值对时，可以考虑将每个键值对建模为包含<code class="literal">key</code>和<code class="literal">value</code>字段的嵌套文档。

相反，可以考虑使用<a class="xref" href="flattened.html" title="Flattened datatype">flattened</a>数据类型，它将整个对象映射为单个字段，并允许对其内容进行简单的搜索。

嵌套的文档及其查询的代价通常是很高的，因此对于这个用例使用<code class="literal">flattened</code>数据类型是一个更好的选择。
</p>
</div>
</div>
<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="nested-arrays-flattening-objects"></a>对象数组是如何扁平化的?
</h3>
</div></div></div>
<p>
Elasticsearch没有内部对象的概念。

因此，它将对象层次结构简化为字段名称和值的简单列表。

例如，考虑以下文档：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index/_doc/1
{
  "group" : "fans",
  "user" : [ <a id="CO306-1"></a><i class="conum" data-value="1"></i>
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/671.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO306-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>字段<code class="word">user</code>是自动添加的，其字段类型为<code class="literal">object</code>。</p>
</td>
</tr>
</table>
</div>
<p>上面的文档将在内部转换成如下所示的文档：</p>
<div class="pre_wrapper lang-js">
<pre class="programlisting prettyprint lang-js">{
  "group" :        "fans",
  "user.first" : [ "alice", "john" ],
  "user.last" :  [ "smith", "white" ]
}</pre>
</div>
<p>
<code class="word">user.first</code>和<code class="word">user.last</code>字段被展平为多值字段，<code class="word">alice</code>和<code class="word">white</code>之间的关联丢失。

该文档将错误地匹配查询<code class="word">alice AND smith</code>：
</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">GET my_index/_search
{
  "query": {
    "bool": {
      "must": [
        { "match": { "user.first": "Alice" }},
        { "match": { "user.last":  "Smith" }}
      ]
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/672.console"></div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="nested-fields-array-objects"></a>将<code class="literal">nested</code>字段用于对象数组
</h3>
</div></div></div>
<p>如果需要索引对象数组并保持数组中每个对象的独立性，请使用<code class="literal">nested</code>数据类型而不是<a class="xref" href="object.html" title="object数据类型" rel="nofollow"><code class="literal">object</code></a>数据类型。</p>
<p>在内部，嵌套对象将数组中的每个对象作为单独的隐藏文档进行索引，这意味着可以使用<a class="xref" href="query-dsl-nested-query.html" title="嵌套查询"><code class="literal">nested</code>查询</a>独立于其他对象来查询每个嵌套对象：</p>
<div class="pre_wrapper lang-console">
<pre class="programlisting prettyprint lang-console">PUT my_index
{
  "mappings": {
    "properties": {
      "user": {
        "type": "nested" <a id="CO307-1"></a><i class="conum" data-value="1"></i>
      }
    }
  }
}

PUT my_index/_doc/1
{
  "group" : "fans",
  "user" : [
    {
      "first" : "John",
      "last" :  "Smith"
    },
    {
      "first" : "Alice",
      "last" :  "White"
    }
  ]
}

GET my_index/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "Smith" }} <a id="CO307-2"></a><i class="conum" data-value="2"></i>
          ]
        }
      }
    }
  }
}

GET my_index/_search
{
  "query": {
    "nested": {
      "path": "user",
      "query": {
        "bool": {
          "must": [
            { "match": { "user.first": "Alice" }},
            { "match": { "user.last":  "White" }} <a id="CO307-3"></a><i class="conum" data-value="3"></i>
          ]
        }
      },
      "inner_hits": { <a id="CO307-4"></a><i class="conum" data-value="4"></i>
        "highlight": {
          "fields": {
            "user.first": {}
          }
        }
      }
    }
  }
}</pre>
</div>
<div class="console_widget" data-snippet="snippets/673.console"></div>
<div class="calloutlist">
<table border="0" summary="Callout list">
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO307-1"><i class="conum" data-value="1"></i></a></p>
</td>
<td align="left" valign="top">
<p>字段<code class="literal">word</code>被映射为<code class="literal">nested</code>类型，而不是<code class="literal">object</code>。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO307-2"><i class="conum" data-value="2"></i></a></p>
</td>
<td align="left" valign="top">
<p>这个查询不能匹配（该文档），因为<code class="word">Alice</code>和<code class="word">Smith</code>不是在同一个嵌套对象里。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO307-3"><i class="conum" data-value="3"></i></a></p>
</td>
<td align="left" valign="top">
<p>这个查询能匹配，因为<code class="word">Alice</code>和<code class="word">White</code>是在同一个嵌套对象里。</p>
</td>
</tr>
<tr>
<td align="left" valign="top" width="5%">
<p><a href="#CO307-4"><i class="conum" data-value="4"></i></a></p>
</td>
<td align="left" valign="top">
<p><code class="literal">inner_hits</code>允许突出显示匹配的嵌套文档。</p>
</td>
</tr>
</table>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="nested-accessing-documents"></a>与<code class="literal">nested</code>文档交互
</h3>
</div></div></div>
<p>嵌套文档可以：</p>
<div class="ulist itemizedlist">
<ul class="itemizedlist">
<li class="listitem">
使用<a class="xref" href="query-dsl-nested-query.html" title="Nested query"><code class="literal">nested</code></a>查询对其进行查询。
</li>
<li class="listitem">
使用<a class="xref" href="search-aggregations-bucket-nested-aggregation.html" title="嵌套聚合"><code class="literal">nested</code></a>和<a class="xref" href="search-aggregations-bucket-reverse-nested-aggregation.html" title="反向嵌套聚合"><code class="literal">reverse_nested</code></a>聚合对其进行分析
</li>
<li class="listitem">
使用<a class="xref" href="search-request-body.html#nested-sorting" title="使用嵌套排序" rel="nofollow">嵌套排序</a>进行排序。
</li>
<li class="listitem">
使用<a class="xref" href="search-request-body.html#nested-inner-hits" title="嵌套内部命中" rel="nofollow">嵌套内部命中</a>来获取并高亮。
</li>
</ul>
</div>
<div class="important admon">
<div class="icon"></div>
<div class="admon_content">
<p>
因为嵌套文档是作为单独的文档进行索引的，所以只能在<code class="literal">nested</code>查询、<code class="literal">nested</code>/<code class="literal">reverse_nested</code>聚合或<a class="xref" href="search-request-body.html#nested-inner-hits" title="嵌套内部命中" rel="nofollow">嵌套内部命中</a>的范围内访问它们。
</p>
<p>
例如，如果嵌套文档中的字符串字段将<a class="xref" href="index-options.html" title="index_options" rel="nofollow"><code class="literal">index_options</code></a>设置为<code class="literal">offsets</code>以允许在高亮阶段使用发布，则这些 offsets 在高亮阶段(主要阶段之一)将不可用。

相反，高亮需要通过<a class="xref" href="search-request-body.html#nested-inner-hits" title="嵌套内部命中">嵌套内部命中</a>来执行。

在通过<a class="xref" href="run-a-search.html#docvalue-fields" title="文档值字段" rel="nofollow"><code class="literal">docvalue_fields</code></a>或<a class="xref" href="search-request-body.html#request-body-search-stored-fields" title="存储字段" rel="nofollow"><code class="literal">stored_fields</code></a>进行搜索的过程中加载字段时，同样的注意事项也适用。
</p>
</div>
</div>
</div>

<div class="section">
<div class="titlepage"><div><div>
<h3 class="title">
<a id="nested-params"></a><code class="literal">nested</code>字段的参数
</h3>
</div></div></div>
<p>
<code class="literal">nested</code>字段接受下列参数：
</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<a class="xref" href="dynamic.html" title="dynamic"><code class="literal">dynamic</code></a>
</span>
</dt>
<dd>
(可选，字符串)
新属性(<code class="literal">properties</code>)是否应该被动态的添加到一个已有的嵌套对象中。

接受<code class="literal">true</code>(默认)，<code class="literal">false</code>及<code class="literal">strict</code>。
</dd>
<dt>
<span class="term">
<a class="xref" href="properties.html" title="properties"><code class="literal">properties</code></a>
</span>
</dt>
<dd>
(可选，对象)
嵌套对象内的字段，可以认识任意一种<a class="xref" href="mapping-types.html" title="字段数据类型">数据类型</a>，包含<code class="literal">nested</code>。

新属性可能会被添加到一个已有的嵌套对象。
</dd>
<dt>
<span class="term">
<code class="literal">include_in_parent</code>
</span>
</dt>
<dd>
(可选，布尔)

如果为<code class="literal">true</code>，嵌套对象中的所有字段也将作为标准(扁平的)字段添加到父文档中。

默认为<code class="literal">false</code>。
</dd>
<dt>
<span class="term">
<code class="literal">include_in_root</code>
</span>
</dt>
<dd>
(可选，布尔)

如果为<code class="literal">true</code>，嵌套对象中的所有字段也将作为标准(扁平的)字段添加到根文档中。

默认为<code class="literal">false</code>。
</dd>
</dl>
</div>
<h3>
<a id="_limits_on_nested_mappings_and_objects"></a><code class="literal">nested</code>映射和对象的限制
</h3>
<p>
如前所述，每个嵌套对象都作为一个单独的 Lucene 文档进行索引。

接着前面的例子，如果我们索引一个包含 100 个<code class="word">user</code>对象的文档，那么将会创建 101 个 Lucene 文档：父文档一个，每个嵌套对象一个。

由于与<code class="literal">nested</code>映射相关的开销，Elasticsearch 进行了一些设置来防止性能问题:
</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<code class="literal">index.mapping.nested_fields.limit</code>
</span>
</dt>
<dd>
一个索引中不同<code class="literal">nested</code>映射的最大数量。

<code class="literal">nested</code>类型应该只在特殊情况下使用，即当对象数组需要彼此独立地查询时。

为了防止映射设计不当，该设置限制了每个索引的唯一<code class="literal">nested</code>类型的数量。

默认值为<code class="literal">50</code>。
</dd>
</dl>
</div>
<p>在前面的例子中，<code class="word">user</code>映射对这个限制只计为 1。</p>
<div class="variablelist">
<dl class="variablelist">
<dt>
<span class="term">
<code class="literal">index.mapping.nested_objects.limit</code>
</span>
</dt>
<dd>
单个文档在所有<code class="literal">nested</code>类型中可以包含的嵌套 JSON 对象的最大数量。

当文档包含太多嵌套对象时，此限制有助于防止内存不足错误。

默认值为<code class="literal">10000</code>。
</dd>
</dl>
</div>
<p>
为了说明这个设置是如何工作的，考虑在前面的示例映射中添加另一个名为<code class="word">comments</code>的<code class="literal">nested</code>类型。

对于每个文档，它包含的<code class="word">user</code>和<code class="word">comment</code>对象的总数必须低于该限制。
</p>
<p>有关防止映射爆炸的其他设置，请参考<a class="xref" href="mapping.html#mapping-limit-settings" title="Settings to prevent mappings explosion">防止映射爆炸的设置</a>。</p>
</div>

</div>
<div class="navfooter">
<span class="prev">
<a href="keyword.html">« keyword(关键词)数据类型</a>
</span>
<span class="next">
<a href="number.html">numeric(数值)数据类型 »</a>
</span>
</div>
</div>

                  <!-- end body -->
                        </div>
                        <div class="col-xs-12 col-sm-4 col-md-4" id="right_col">
                        
                        </div>
                    </div>
                </div>
            </section>
        </div>
    </section>
</div>
<script src="../static/cn.js"></script>
</body>
</html>